package com.icesoft.system.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.icesoft.framework.core.controller.BaseCrudRestController;
import com.icesoft.framework.core.entity.Dictionary;
import com.icesoft.framework.core.util.V;
import com.icesoft.framework.core.vo.*;
import com.icesoft.system.annotation.ConstructDictionary;
import com.icesoft.system.permission.OperationCons;
import com.icesoft.system.permission.annotation.BindPermission;
import com.icesoft.system.service.impl.DictionaryServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

/**
 * 数据字典相关Controller
 *
 * @author MyName
 * @version 1.0
 * @date 2023-02-06
 * Copyright © MyCompany
 */
@Slf4j
@RestController
@RequiredArgsConstructor
@BindPermission(name = "数据字典")
@RequestMapping("/system/dictionary")
public class DictionaryController extends BaseCrudRestController<Dictionary> {

	private final ApplicationContext context;

	private final DictionaryServiceImpl dictionaryService;

	/**
	 * 查询ViewObject的分页数据
	 * <p>
	 * url请求参数示例: /list?name=abc&pageSize=20&pageIndex=1&orderBy=name
	 * </p>
	 *
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/query")
	@BindPermission(name = OperationCons.LABEL_LIST, code = OperationCons.CODE_READ)
	public JsonResult getViewObjectListMapping(Dictionary entity, Pagination pagination) throws Exception {
		pagination.setOrderBy("id:AES");
		return super.getViewObjectList(entity, pagination, DictionaryVO.class);
	}

	/**
	 * 根据资源id查询ViewObject
	 *
	 * @param id ID
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/{id}")
	@BindPermission(name = OperationCons.LABEL_DETAIL, code = OperationCons.CODE_READ)
	public JsonResult getViewObjectMapping(@PathVariable("id") Long id) throws Exception {
		return super.getViewObject(id, DictionaryVO.class);
	}

	/**
	 * 创建资源对象
	 *
	 * @param entityVO
	 * @return JsonResult
	 * @throws Exception
	 */
	@PostMapping("/create")
	@BindPermission(name = OperationCons.LABEL_CREATE, code = OperationCons.CODE_WRITE)
	public JsonResult createEntityMapping(@RequestBody @Valid DictionaryVO entityVO) throws Exception {
		boolean success = dictionaryService.createDictAndChildren(entityVO);
		if (!success) {
			return JsonResult.FAIL_OPERATION("保存数据字典失败！");
		}
		return JsonResult.OK();
	}

	/**
	 * 根据ID更新资源对象
	 *
	 * @param entityVO
	 * @return JsonResult
	 * @throws Exception
	 */
	@PostMapping("/update/{id}")
	@BindPermission(name = OperationCons.LABEL_UPDATE, code = OperationCons.CODE_WRITE)
	public JsonResult updateEntityMapping(@PathVariable("id") Long id, @Valid @RequestBody DictionaryVO entityVO) throws Exception {
		entityVO.setId(id);
		boolean success = dictionaryService.updateDictAndChildren(entityVO);
		if (!success) {
			return JsonResult.FAIL_OPERATION("更新数据字典失败！");
		}

		Map<String, Object> listenerBeans = context.getBeansWithAnnotation(ConstructDictionary.class);
		listenerBeans.forEach((type, bean) -> {
			ConstructDictionary annotation = bean.getClass().getAnnotation(ConstructDictionary.class);
			List<Dictionary> itemsList = dictionaryService.getByType(annotation.value());

			for (Field field : bean.getClass().getFields()) {
				for (Dictionary dictionary : itemsList) {
					if (dictionary.getItemCode().equals(field.getName())) {
						try {
							String typeName = bean.getClass().getField(field.getName()).getType().getSimpleName();
							if (typeName.equals("boolean") || typeName.equals("Boolean")) {
								bean.getClass().getField(field.getName()).set(bean, Boolean.parseBoolean(dictionary.getItemValue()));
							}

							if (typeName.equals("int") || typeName.equals("Integer")) {
								bean.getClass().getField(field.getName()).set(bean, Integer.parseInt(dictionary.getItemValue()));
							}

							if (typeName.equals("String")) {
								bean.getClass().getField(field.getName()).set(bean, dictionary.getItemValue());
							}


						} catch (NoSuchFieldException | IllegalAccessException e) {
							throw new RuntimeException(e);
						}
					}
				}
			}
		});

		return JsonResult.OK();
	}

	/**
	 * 根据id删除资源对象
	 *
	 * @param id
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/delete/{id}")
	@BindPermission(name = OperationCons.LABEL_DELETE, code = OperationCons.CODE_WRITE)
	public JsonResult deleteEntityMapping(@PathVariable("id") Long id) throws Exception {
		boolean success = dictionaryService.deleteDictAndChildren(id);
		if (!success) {
			return JsonResult.FAIL_OPERATION("删除数据字典失败！");
		}
		return JsonResult.OK();
	}

	/**
	 * 获取数据字典数据列表
	 *
	 * @param type
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/items/{type}")
	@BindPermission(name = "获取数据字典数据列表", code = OperationCons.CODE_READ)
	public JsonResult getItems(@PathVariable("type") String type) throws Exception {
		if (V.isEmpty(type)) {
			return JsonResult.FAIL_INVALID_PARAM("type参数未指定");
		}
		List<LabelValue> itemsList = dictionaryService.getLabelValueList(type);
		return JsonResult.OK(itemsList);
	}

	/**
	 * 校验类型编码是否重复
	 *
	 * @param id
	 * @param type
	 * @return
	 */
	@GetMapping("/checkTypeDuplicate")
	@BindPermission(name = "校验类型编码是否重复", code = OperationCons.CODE_READ)
	public JsonResult checkTypeDuplicate(@RequestParam(required = false) Long id, @RequestParam String type) {
		if (V.notEmpty(type)) {
			LambdaQueryWrapper<Dictionary> wrapper = new LambdaQueryWrapper();
			wrapper.select(Dictionary::getId).eq(Dictionary::getType, type).eq(Dictionary::getParentId, 0);
			if (V.notEmpty(id)) {
				wrapper.ne(Dictionary::getId, id);
			}
			boolean alreadyExists = dictionaryService.exists(wrapper);
			if (alreadyExists) {
				return new JsonResult(Status.FAIL_OPERATION, "类型编码已存在");
			}
		}
		return JsonResult.OK();
	}
}